#pragma once
#include <mydll.h>
#include <list>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <mymutex.hxx>
#include <macro.hxx>
#include "action.hxx"

#pragma warning(disable : 4251)
#pragma warning(disable : 4267)

using namespace std;

typedef void CURL;
typedef void CURLSH;
class FileLog;
class GisusDB;
class TaskManager;
class Keyword;
class User;

class Threader : public Thread
{
public:
	Threader(Task* task1, string url1) : task(task1), url(url1)
	{
		Start();
	}

protected:
	virtual void Execute(Thread::Arg arg);
private:
	Task* task;
	string url;
};

class EXPORT Task
{
public:
	typedef map<string, string> ClientInfos;

	typedef enum{
		NEW_CAR_CHOOSE_NO = 0,
		INUSE_CAR_CHOOSE_NO = 1
	}TaskType;

	typedef enum
	{
		SUCCEEDED = 0,
		CREATED = 1,
		LOADED = 2,
		REGISTRRED,
		INVALID_TASK,
		ZOMBIE_SEED,
		CON_INUSE,
		DELETED,
		FROZEN = 10,	// HOT_SEED=9 deleted.
		HPHM_REFRESHED,
		IN_CHOOSING,
		IN_FINISH,
		PAID
	}TaskStatus;

	typedef struct HPHMParam
	{
		HPHMParam(std::map<int, string>& sizehphm2, std::string url2):sizehphm(sizehphm2), url(url2)
		{}
		std::map<int, std::string> sizehphm;
		std::string url;
	}tHPHMParam;

	Task(FileLog* filelog = 0);
	Task(const User* user, int id, const string& taskInfo, TaskStatus status = LOADED, FileLog* filelog = 0);
	Task(const Task& model);
	~Task();

	int SaveTask();
	bool Delete(void);
	bool MarkPaid(void);
	bool Restore(void);

	virtual Action::ActionResult Execute(Action::ActionType Type, string& errmsg);
	virtual Action::ActionResult Register(string& errmsg);
	virtual Action::ActionResult Refresh(string& errmsg);
	virtual Action::ActionResult Refreshhphm(string& errmsg);
	virtual Action::ActionResult RefreshCaptcha(string& errmsg);
	virtual Action::ActionResult Query(string& errmsg);
	virtual Action::ActionResult ReturnQuery(string& errmsg);
	virtual Action::ActionResult Choose(string& errmsg);
	virtual Action::ActionResult Finish(string& errmsg);
	virtual Action::ActionResult Decaptcha(string& errmsg);
	virtual Action::ActionResult Refund(string& errmsg);
	virtual Action* NextAction(void);
	Action* NextActionQ(void);
	Action* NextActionC(void);

	void DisplayMsg(string msg, int msgType);

	int ValidateProxy(const string& proxy, string& errmsg);
	Action* GetQAction(const string& spec, const string& avoidchars1);

	bool Update(void);
	bool MarkStatus(bool isZombie = false);
	int NewZombie(void);

	bool IsBusy(void) const;
	bool IsValid() const;
	string ToString() const;

	char* GetCaptcha(size_t& size) const;
	bool SetCaptcha(const string& captcha);
	bool ResetCaptcha(void);

	void SetFileLog(FileLog* filelog);
	void SetManager(TaskManager* manager1);
	void SetGisusDB(GisusDB* gisusdb);

	bool RePort(bool force = false);
	void InvalidProxy(void);

	const std::map<string, string>& GetResults(void) const;

	string Signature(void) const;
	bool IsExpiring(void) const;
	bool IsExpired(void) const;
	bool TimeToRefreshCaptcha(void) const;
	bool IsCaptchaRefreshed(void) const;
	bool IsPTask(void) const;
	bool IsCaptchaed(void) const;
	bool IsMatched(const std::string& result) const;
	bool IsTerminated(void) const;

	string StatusDes(void) const;
	string Getpromptmsg(void) const;
	int GetQueriedCount(void) const;

	int PerformStep(CURL* curl, const string& url, stringstream& bodystream, const string& dataFields="", int countTry=7);

	void Downloadhphm(std::string url);

	/* Getters for detailed infos. */
	PROPERTY_TASKINFO(cjh);
	PROPERTY_TASKINFO(clxh);
	PROPERTY_TASKINFO(fdjh);
	PROPERTY_TASKINFO(fpbh);
	PROPERTY_TASKINFO(lsh);
	PROPERTY_TASKINFO(xm);
	PROPERTY_TASKINFO(sfzh);
	PROPERTY_TASKINFO(yzbm);
	PROPERTY_TASKINFO(dz);
	PROPERTY_TASKINFO(No);
	PROPERTY_TASKINFO(zjzl);
	PROPERTY_TASKINFO(zjhm);
	PROPERTY_TASKINFO(tel);
	PROPERTY_TASKINFO(city);
	PROPERTY_TASKINFO(bld);
	PROPERTY_TASKINFO(lqc);
	PROPERTY_TASKINFO(xzhq);
	PROPERTY_TASKINFO(slrq);
	PROPERTY_TASKINFO(CR);
	PROPERTY_TASKINFO(kwds);
	PROPERTY_TASKINFO(avoidchars);
	PROPERTY_TASKINFO(spec);
	PROPERTY_TASKINFO(result);
	PROPERTY_TASKINFO(dlr);
	PROPERTY_TASKINFO(dlrsfzhm);
	PROPERTY_TASKINFO(dlrlxdh);
	PROPERTY_TASKINFO(dlrdz);
	PROPERTY_TASKINFO(latesl);

	PROPERTY(Owner, const User*);
	PROPERTY(Id, int);
	PROPERTY(Type, TaskType);
	PROPERTY(Status, TaskStatus);
	PROPERTY(Port, std::string);
	PROPERTY(ChooseUrl, std::string);
	PROPERTY(Age, int);

protected:
	friend TaskManager;
	friend Action;

	virtual Action::ActionResult RegisterInternal(string& errmsg, int stopstep=0);

	Action* queryAction;
	Action* captchaAction;

	stringstream bodystream;
	stringstream captchastream;
	string captcha;
	stringstream captchastreamD;
	string captchaD;

	TaskManager* manager;
	GisusDB* gisusdb;
	CURL* curl;
	CURL* curlCaptcha;
	CURLSH* curlSH;

	mutable Mutex curlInUse;
	mutable Mutex curlCaptchaInUse;
	mutable Mutex stateInUse;

	mutable ClientInfos clientInfos;
	std::map<string, string> results;

	mutable std::map<string, int> queriedCounts;
	std::map<int, std::string> sizehphm;

	time_t lastQueryStarted;
	time_t lastActivated;
	time_t lastBirth;

	int genId;

	int performRes;
	int step;

	string proxy;

	bool released;

	FileLog* _filelog;

	Action::ActionResult CheckQueryResult(stringstream& bodystream, std::map<string, string>& results, string& errmsg, long& totalCount, long& zxrs);
	Action::ActionResult CheckFinishResult(stringstream& bodystream, string& errmsg);
	Action::ActionResult CheckWatchResult(stringstream& bodystream,  int& newAvailableNum);

	Action::ActionResult QueryRaw(string& errmsg);
	Action::ActionResult RefreshRaw(void);
	Action::ActionResult RefreshCaptchaRaw(string& errmsg);
	Action::ActionResult PickResultRaw(string& errmsg);

	bool Parse(const string& taskInfo);

	virtual void PreAction(Action* action);
	virtual void AfterAction(Action* action);

	bool ShallRefund(void) const;

	void CleanCurls(void);
};
